/*
 * AStarPathFinding Library - Copyright (c) Muhammad Ahmed - quteahmed@gmail.com
 * 
 * This software is provided 'as-is', without any express or
 * implied warranty. In no event will the authors be held
 * liable for any damages arising from the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute
 * it freely, subject to the following restrictions:
 * 
 * 1. The origin of this software must not be misrepresented;
 * you must not claim that you wrote the original software.
 * If you use this software in a product, an acknowledgment
 * in the product documentation would be appreciated but
 * is not required.
 * 
 * 2. Altered source versions must be plainly marked as such,
 * and must not be misrepresented as being the original software.
 * 
 * 3. This notice may not be removed or altered from any
 * source distribution.
 */
package com.astar.library;

public class PathFinder {
	public static boolean AStar(NodeMap Map, int StartX, int StartY, int EndX, int EndY) {
		return AStar(Map, Map.getNode(StartX, StartY), Map.getNode(EndX, EndY));
	}

	public static boolean AStar(NodeMap Map, Node Start, Node End)
	{
		if (Start != null && End != null)
		{
			if (Start.getMapParent() == Map && End.getMapParent() == Map)
			{
				boolean PathFound = true;
				BinaryHeap OpenList = new BinaryHeap();
				BinaryHeap ClosedList = new BinaryHeap();
				OpenList.add(Start);
				Start.onOpenList = true;
				while (!End.onClosedList)
				{
					if (OpenList.size() > 0)
					{
						Node Current = OpenList.remove();
						ClosedList.add(Current);
						Current.onClosedList = true;
						Node[] Surrounding = Current.getSurroundingNodes();
						for (Node Next : Surrounding)
						{
							if (Next.getCost() > 0 && !Next.onClosedList)
							{
								if (!Next.onOpenList)
								{
									Next.setParent(Current);
									//To do: Check to see if we are moving diagonally, if so increase the cost.
									Next.setG(Current.getG() + Next.getG());//G = Current.G + Next.Cost;
									Next.setH(Next.calcHeuristic(End));//Next.H = Next.CalcHeuristic(End);
									OpenList.add(Next);
									Next.onOpenList = true;
								}
								else
								{
									if (Current.getG() > (Next.getG() + Current.getCost()))
									{
										Current.setParent(Next);//Current.Parent = Next;
										Current.setG(Next.getG() + Current.getCost());//.G = Next.G + Current.Cost;
										//The way the binary heap works makes us have to remove and re-add the item.
										OpenList.remove(Current);
										OpenList.add(Current);
									}
								}
							}
						}
					}
					else
					{
						PathFound = false;
						break;
					}
				}
				OpenList.clear();
				ClosedList.clear();
				return PathFound;
			}
			else
			{
				//throw new Exception("Start or End Node does not belong to the NodeMap passed into the function.");
			}
		}
		else
		{
			//throw new Exception("Start or End Node were not initialised, ensure they are initialised and belong to a NodeMap.");
		}

		return false;
	}
}
